home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / mkroom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  16.0 KB  |  717 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)mkroom.c    3.1    93/04/04    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * Entry points:
  7.  *    mkroom() -- make and stock a room of a given type
  8.  *    nexttodoor() -- return TRUE if adjacent to a door
  9.  *    has_dnstairs() -- return TRUE if given room has a down staircase
  10.  *    has_upstairs() -- return TRUE if given room has an up staircase
  11.  *    courtmon() -- generate a court monster
  12.  *    save_rooms() -- save rooms into file fd
  13.  *    rest_rooms() -- restore rooms from file fd
  14.  */
  15.  
  16. #include "hack.h"
  17.  
  18. #ifdef OVLB
  19. static boolean FDECL(isbig, (struct mkroom *));
  20. static struct mkroom * FDECL(pick_room,(BOOLEAN_P));
  21. static void NDECL(mkshop), FDECL(mkzoo,(int)), NDECL(mkswamp);
  22. static void NDECL(mktemple);
  23. static coord * FDECL(shrine_pos, (int));
  24. static struct permonst * NDECL(morguemon);
  25. #ifdef ARMY
  26. static struct permonst * NDECL(squadmon);
  27. #endif
  28. static void FDECL(save_room, (int,struct mkroom *));
  29. static void FDECL(rest_room, (int,struct mkroom *));
  30. #endif /* OVLB */
  31.  
  32. #define sq(x) ((x)*(x))
  33.  
  34. extern const struct shclass shtypes[];    /* defined in shknam.c */
  35.  
  36. #ifdef OVLB
  37.  
  38. static boolean
  39. isbig(sroom)
  40. register struct mkroom *sroom;
  41. {
  42.     register int area = (sroom->hx - sroom->lx + 1)
  43.                * (sroom->hy - sroom->ly + 1);
  44.     return((boolean)( area > 20 ));
  45. }
  46.  
  47. void
  48. mkroom(roomtype)
  49. /* make and stock a room of a given type */
  50. int    roomtype;
  51. {
  52.     if (roomtype >= SHOPBASE)
  53.     mkshop();    /* someday, we should be able to specify shop type */
  54.     else switch(roomtype) {
  55.     case COURT:    mkzoo(COURT); break;
  56.     case ZOO:    mkzoo(ZOO); break;
  57.     case BEEHIVE:    mkzoo(BEEHIVE); break;
  58.     case MORGUE:    mkzoo(MORGUE); break;
  59.     case BARRACKS:    mkzoo(BARRACKS); break;
  60.     case SWAMP:    mkswamp(); break;
  61.     case TEMPLE:    mktemple(); break;
  62.     default:    impossible("Tried to make a room of type %d.", roomtype);
  63.     }
  64. }
  65.  
  66. static void
  67. mkshop()
  68. {
  69.     register struct mkroom *sroom;
  70.     int i = -1;
  71. #ifdef WIZARD
  72. # ifdef GCC_WARN
  73.     register char *ep = (char *)0;
  74. # else
  75.     register char *ep;
  76. # endif
  77.  
  78.     /* first determine shoptype */
  79.     if(wizard){
  80.         ep = getenv("SHOPTYPE");
  81.         if(ep){
  82.             if(*ep == 'z' || *ep == 'Z'){
  83.                 mkzoo(ZOO);
  84.                 return;
  85.             }
  86.             if(*ep == 'm' || *ep == 'M'){
  87.                 mkzoo(MORGUE);
  88.                 return;
  89.             }
  90.             if(*ep == 'b' || *ep == 'B'){
  91.                 mkzoo(BEEHIVE);
  92.                 return;
  93.             }
  94.             if(*ep == 't' || *ep == 'T' || *ep == '\\'){
  95.                 mkzoo(COURT);
  96.                 return;
  97.             }
  98. #ifdef ARMY
  99.             if(*ep == 's' || *ep == 'S'){
  100.                 mkzoo(BARRACKS);
  101.                 return;
  102.             }
  103. #endif /* ARMY */
  104.             if(*ep == '_'){
  105.                 mktemple();
  106.                 return;
  107.             }
  108.             if(*ep == '}'){
  109.                 mkswamp();
  110.                 return;
  111.             }
  112.             for(i=0; shtypes[i].name; i++)
  113.                 if(*ep == def_oc_syms[(int)shtypes[i].symb])
  114.                     goto gottype;
  115.             if(*ep == 'g' || *ep == 'G')
  116.                 i = 0;
  117.             else
  118.                 i = -1;
  119.         }
  120.     }
  121. gottype:
  122. #endif
  123.     for(sroom = &rooms[0]; ; sroom++){
  124.         if(sroom->hx < 0) return;
  125.         if(sroom - rooms >= nroom) {
  126.             pline("rooms not closed by -1?");
  127.             return;
  128.         }
  129.         if(sroom->rtype != OROOM) continue;
  130.         if(has_dnstairs(sroom) || has_upstairs(sroom))
  131.             continue;
  132.         if(
  133. #ifdef WIZARD
  134.            (wizard && ep && sroom->doorct != 0) ||
  135. #endif
  136.             sroom->doorct == 1) break;
  137.     }
  138.     if (!sroom->rlit) {
  139.         int x, y;
  140.  
  141.         for(x = sroom->lx - 1; x <= sroom->hx + 1; x++)
  142.         for(y = sroom->ly - 1; y <= sroom->hy + 1; y++)
  143.             levl[x][y].lit = 1;
  144.         sroom->rlit = 1;
  145.     }
  146.  
  147.     if(i < 0) {            /* shoptype not yet determined */
  148.         register int j;
  149.  
  150.         /* pick a shop type at random */
  151.         for (j = rnd(100), i = 0; (j -= shtypes[i].prob) > 0; i++)
  152.         continue;
  153.  
  154.         /* big rooms cannot be wand or book shops,
  155.          * - so make them general stores
  156.          */
  157.         if(isbig(sroom) && (shtypes[i].symb == WAND_CLASS
  158.                 || shtypes[i].symb == SPBOOK_CLASS)) i = 0;
  159.     }
  160.     sroom->rtype = SHOPBASE + i;
  161.  
  162.     /* set room bits before stocking the shop */
  163. #ifdef SPECIALIZATION
  164.     topologize(sroom, FALSE); /* doesn't matter - this is a special room */
  165. #else
  166.     topologize(sroom);
  167. #endif
  168.  
  169.     /* stock the room with a shopkeeper and artifacts */
  170.     stock_room(i, sroom);
  171. }
  172.  
  173. static struct mkroom *
  174. pick_room(strict)
  175. register boolean strict;
  176. /* pick an unused room, preferably with only one door */
  177. {
  178.     register struct mkroom *sroom;
  179.     register int i = nroom;
  180.  
  181.     for(sroom = &rooms[rn2(nroom)]; i--; sroom++) {
  182.         if(sroom == &rooms[nroom])
  183.             sroom = &rooms[0];
  184.         if(sroom->hx < 0)
  185.             return (struct mkroom *)0;
  186.         if(sroom->rtype != OROOM)    continue;
  187.         if(!strict) {
  188.             if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
  189.             continue;
  190.         } else if(has_upstairs(sroom) || has_dnstairs(sroom))
  191.             continue;
  192.         if(sroom->doorct == 1 || !rn2(5)
  193. #ifdef WIZARD
  194.                         || wizard
  195. #endif
  196.                             )
  197.             return sroom;
  198.     }
  199.     return (struct mkroom *)0;
  200. }
  201.  
  202. static void
  203. mkzoo(type)
  204. int type;
  205. {
  206.     register struct mkroom *sroom;
  207.  
  208.     if ((sroom = pick_room(FALSE)) != 0) {
  209.         sroom->rtype = type;
  210.         fill_zoo(sroom);
  211.     }
  212. }
  213.  
  214. void
  215. fill_zoo(sroom)
  216. struct mkroom *sroom;
  217. {
  218.     struct monst *mon;
  219.     register int sx,sy,i;
  220.     int sh, tx, ty, goldlim, type = sroom->rtype;
  221.     int rmno = (sroom - rooms) + ROOMOFFSET;
  222.     coord mm;
  223.  
  224. #ifdef GCC_WARN
  225.     tx = ty = goldlim = 0;
  226. #endif
  227.  
  228.     sh = sroom->fdoor;
  229.     switch(type) {
  230.         case COURT:
  231.         if(level.flags.is_maze_lev) {
  232.             for(tx = sroom->lx; tx <= sroom->hx; tx++)
  233.             for(ty = sroom->ly; ty <= sroom->hy; ty++)
  234.                 if(IS_THRONE(levl[tx][ty].typ))
  235.                 goto throne_placed;
  236.         }
  237.         i = 100;
  238.         do {    /* don't place throne on top of stairs */
  239.             (void) somexy(sroom, &mm);
  240.             tx = mm.x; ty = mm.y;
  241.         } while (occupied((xchar)tx, (xchar)ty) && --i > 0);
  242.         throne_placed:
  243.         /* TODO: try to ensure the enthroned monster is an M2_PRINCE */
  244.         break;
  245.         case BEEHIVE:
  246.         tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2;
  247.         ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2;
  248.         if(sroom->irregular) {
  249.             /* center might not be valid, so put queen elsewhere */
  250.             if(levl[tx][ty].roomno != rmno || levl[tx][ty].edge) {
  251.             (void) somexy(sroom, &mm);
  252.             tx = mm.x; ty = mm.y;
  253.             }
  254.         }
  255.         break;
  256.         case ZOO:
  257.         goldlim = 500 * level_difficulty();
  258.         break;
  259.     }
  260.     for(sx = sroom->lx; sx <= sroom->hx; sx++)
  261.         for(sy = sroom->ly; sy <= sroom->hy; sy++) {
  262.         if(sroom->irregular) {
  263.             if(levl[sx][sy].roomno != rmno ||
  264.                levl[sx][sy].edge ||
  265.               (sroom->doorct &&
  266.                distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1))
  267.             continue;
  268.         } else if(!SPACE_POS(levl[sx][sy].typ) ||
  269.               (sroom->doorct &&
  270.                ((sx == sroom->lx && doors[sh].x == sx-1) ||
  271.                 (sx == sroom->hx && doors[sh].x == sx+1) ||
  272.                 (sy == sroom->ly && doors[sh].y == sy-1) ||
  273.                 (sy == sroom->hy && doors[sh].y == sy+1))))
  274.             continue;
  275.         /* don't place monster on explicitly placed throne */
  276.         if(type == COURT && IS_THRONE(levl[sx][sy].typ))
  277.             continue;
  278.         mon = makemon(
  279.             (type == COURT) ? courtmon() :
  280. #ifdef ARMY
  281.             (type == BARRACKS) ? squadmon() :
  282. #endif
  283.             (type == MORGUE) ? morguemon() :
  284.             (type == BEEHIVE) ?
  285.             (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : 
  286.              &mons[PM_KILLER_BEE]) :
  287.             (struct permonst *) 0,
  288.            sx, sy);
  289.         if(mon) {
  290.             mon->msleep = 1;
  291.             if (type==COURT && mon->mpeaceful) {
  292.                 mon->mpeaceful = 0;
  293.                 set_malign(mon);
  294.             }
  295.         }
  296.         switch(type) {
  297.             case ZOO:
  298.             if(sroom->doorct)
  299.             {
  300.                 int distval = dist2(sx,sy,doors[sh].x,doors[sh].y);
  301.                 i = sq(distval);
  302.             }
  303.             else
  304.                 i = goldlim;
  305.             if(i >= goldlim) i = 5*level_difficulty();
  306.             goldlim -= i;
  307.             mkgold((long) rn1(i, 10), sx, sy);
  308.             break;
  309.             case MORGUE:
  310.             if(!rn2(5))
  311.                 (void) mk_tt_object(CORPSE, sx, sy);
  312.             if(!rn2(10))    /* lots of treasure buried with dead */
  313.                 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
  314.                          sx, sy, TRUE);
  315.             break;
  316.             case BEEHIVE:
  317.             if(!rn2(3))
  318.                 (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, TRUE);
  319.             break;
  320. #ifdef ARMY
  321.             case BARRACKS:
  322.             if(!rn2(20))    /* the payroll and some loot */
  323.                 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
  324.                          sx, sy, TRUE);
  325.             break;
  326. #endif
  327.         }
  328.         }
  329.     switch (type) {
  330.           case COURT:
  331.           levl[tx][ty].typ = THRONE;
  332.           (void) somexy(sroom, &mm);
  333.           mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y);
  334.           (void) mksobj_at(CHEST, mm.x, mm.y, TRUE); /* the royal coffers */
  335.           level.flags.has_court = 1;
  336.           break;
  337. #ifdef ARMY
  338.           case BARRACKS:
  339.           level.flags.has_barracks = 1;
  340.           break;
  341. #endif
  342.           case ZOO:
  343.           level.flags.has_zoo = 1;
  344.           break;
  345.           case MORGUE:
  346.           level.flags.has_morgue = 1;
  347.           break;
  348.           case SWAMP:
  349.           level.flags.has_swamp = 1;
  350.           break;
  351.           case BEEHIVE:
  352.           level.flags.has_beehive = 1;
  353.           break;
  354.     }
  355. }
  356.  
  357. void
  358. mkundead(mm)   /* make a swarm of undead around mm */
  359. coord *mm;
  360. {
  361.     register int cnt = (level_difficulty() + 1)/10 + rnd(5);
  362.     register struct permonst *mdat;
  363.  
  364.     while(cnt--) {
  365.           mdat = morguemon();
  366.           if(enexto(mm, mm->x, mm->y, mdat))
  367.            (void) makemon(mdat, mm->x, mm->y);
  368.     }
  369.     level.flags.graveyard = TRUE;    /* reduced chance for undead corpse */
  370. }
  371.  
  372. static struct permonst *
  373. morguemon()
  374. {
  375.     register int i = rn2(100), hd = rn2(level_difficulty());
  376.  
  377.     if(hd > 10 && i < 10)
  378.         return((Inhell || In_endgame(&u.uz)) ? mkclass(S_DEMON,0) :
  379.                                &mons[ndemon(A_NONE)]);
  380.     if(hd > 8 && i > 85)
  381.         return(mkclass(S_VAMPIRE,0));
  382.  
  383.     return((i < 20) ? &mons[PM_GHOST]
  384.             : (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE,0));
  385. }
  386.  
  387. static void
  388. mkswamp()    /* Michiel Huisjes & Fred de Wilde */
  389. {
  390.     register struct mkroom *sroom;
  391.     register int sx,sy,i,eelct = 0;
  392.  
  393.     for(i=0; i<5; i++) {        /* 5 tries */
  394.         sroom = &rooms[rn2(nroom)];
  395.         if(sroom->hx < 0 || sroom->rtype != OROOM ||
  396.            has_upstairs(sroom) || has_dnstairs(sroom))
  397.             continue;
  398.  
  399.         /* satisfied; make a swamp */
  400.         sroom->rtype = SWAMP;
  401.         for(sx = sroom->lx; sx <= sroom->hx; sx++)
  402.         for(sy = sroom->ly; sy <= sroom->hy; sy++)
  403.         if(!OBJ_AT(sx, sy) &&
  404.            !MON_AT(sx, sy) && !t_at(sx,sy) && !nexttodoor(sx,sy)) {
  405.             if((sx+sy)%2) {
  406.             levl[sx][sy].typ = POOL;
  407.             if(!eelct || !rn2(4)) {
  408.                 /* mkclass() won't do, as we might get kraken */
  409.                 (void) makemon(rn2(5) ? &mons[PM_GIANT_EEL]
  410.                           : &mons[PM_ELECTRIC_EEL],
  411.                         sx, sy);
  412.                 eelct++;
  413.             }
  414.             } else 
  415.             if(!rn2(4))    /* swamps tend to be moldy */
  416.                 (void) makemon(mkclass(S_FUNGUS,0), sx, sy);
  417.         }
  418.         level.flags.has_swamp = 1;
  419.     }
  420. }
  421.  
  422. static coord *
  423. shrine_pos(roomno)
  424. int roomno;
  425. {
  426.     static coord buf;
  427.     struct mkroom *troom = &rooms[roomno - ROOMOFFSET];
  428.  
  429.     buf.x = troom->lx + ((troom->hx - troom->lx) / 2);
  430.     buf.y = troom->ly + ((troom->hy - troom->ly) / 2);
  431.     return(&buf);
  432. }
  433.  
  434. static void
  435. mktemple()
  436. {
  437.     register struct mkroom *sroom;
  438.     coord *shrine_spot;
  439.     register struct rm *lev;
  440.  
  441.     if(!(sroom = pick_room(TRUE))) return;
  442.  
  443.     /* set up Priest and shrine */
  444.     sroom->rtype = TEMPLE;
  445.     /*
  446.      * In temples, shrines are blessed altars
  447.      * located in the center of the room
  448.      */
  449.     shrine_spot = shrine_pos((sroom - rooms) + ROOMOFFSET);
  450.     lev = &levl[shrine_spot->x][shrine_spot->y];
  451.     lev->typ = ALTAR;
  452.     lev->altarmask = induced_align(80);
  453.     priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE);
  454.      lev->altarmask |= AM_SHRINE;
  455.     level.flags.has_temple = 1;
  456. }
  457.  
  458. boolean
  459. nexttodoor(sx,sy)
  460. register int sx, sy;
  461. {
  462.     register int dx, dy;
  463.     register struct rm *lev;
  464.     for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) {
  465.         if(!isok(sx+dx, sy+dy)) continue;
  466.         if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) ||
  467.             lev->typ == SDOOR)
  468.             return(TRUE);
  469.     }
  470.     return(FALSE);
  471. }
  472.  
  473. boolean
  474. has_dnstairs(sroom)
  475. register struct mkroom *sroom;
  476. {
  477.     if (sroom == dnstairs_room)
  478.         return TRUE;
  479.     if (sstairs.sx && !sstairs.up)
  480.         return((boolean)(sroom == sstairs_room));
  481.     return FALSE;
  482. }
  483.  
  484. boolean
  485. has_upstairs(sroom)
  486. register struct mkroom *sroom;
  487. {
  488.     if (sroom == upstairs_room)
  489.         return TRUE;
  490.     if (sstairs.sx && sstairs.up)
  491.         return((boolean)(sroom == sstairs_room));
  492.     return FALSE;
  493. }
  494.  
  495. #endif /* OVLB */
  496. #ifdef OVL0
  497.  
  498. int
  499. somex(croom)
  500. register struct mkroom *croom;
  501. {
  502.     return rn2(croom->hx-croom->lx+1) + croom->lx;
  503. }
  504.  
  505. int
  506. somey(croom)
  507. register struct mkroom *croom;
  508. {
  509.     return rn2(croom->hy-croom->ly+1) + croom->ly;
  510. }
  511.  
  512. boolean
  513. inside_room(croom, x, y)
  514. struct mkroom *croom;
  515. xchar x, y;
  516. {
  517.     return((boolean)(x >= croom->lx-1 && x <= croom->hx+1 &&
  518.         y >= croom->ly-1 && y <= croom->hy+1));
  519. }
  520.  
  521. boolean
  522. somexy(croom, c)
  523. struct mkroom *croom;
  524. coord *c;
  525. {
  526.     int try_cnt = 0;
  527.     int i;
  528.  
  529.     if (croom->irregular) {
  530.         i = (croom - rooms) + ROOMOFFSET;
  531.  
  532.         while(try_cnt++ < 100) {
  533.         c->x = somex(croom);
  534.         c->y = somey(croom);
  535.         if(!levl[c->x][c->y].edge && levl[c->x][c->y].roomno == i)
  536.             return TRUE;
  537.         }
  538.         /* try harder; exhaustively search until one is found */
  539.         for(c->x = croom->lx; c->x <= croom->hx; c->x++)
  540.         for(c->y = croom->ly; c->y <= croom->hy; c->y++)
  541.             if(!levl[c->x][c->y].edge && levl[c->x][c->y].roomno == i)
  542.             return TRUE;
  543.         return FALSE;
  544.     }
  545.  
  546.     if (!croom->nsubrooms) {
  547.         c->x = somex(croom);
  548.         c->y = somey(croom);
  549.         return TRUE;
  550.     }
  551.  
  552.     /* Check that coords doesn't fall into a subroom or into a wall */
  553.  
  554.     while(try_cnt++ < 100) {
  555.         c->x = somex(croom);
  556.         c->y = somey(croom);
  557.         if (IS_WALL(levl[c->x][c->y].typ))
  558.             continue;
  559.         for(i=0 ; i<croom->nsubrooms;i++)
  560.             if(inside_room(croom->sbrooms[i], c->x, c->y))
  561.             goto you_lose;
  562.         break;
  563. you_lose:    ;
  564.     }
  565.     if (try_cnt >= 100)
  566.         return FALSE;
  567.     return TRUE;
  568. }
  569.  
  570. /* 
  571.  * Search for a special room given its type (zoo, court, etc...)
  572.  *     Special values :
  573.  *         - ANY_SHOP
  574.  *         - ANY_TYPE
  575.  */
  576.  
  577. struct mkroom *
  578. search_special(type)
  579. schar type;
  580. {
  581.     register struct mkroom *croom;
  582.  
  583.     for(croom = &rooms[0]; croom->hx >= 0; croom++)
  584.         if((type == ANY_TYPE && croom->rtype != OROOM) ||
  585.            (type == ANY_SHOP && croom->rtype >= SHOPBASE) ||
  586.            croom->rtype == type)
  587.         return croom;
  588.     for(croom = &subrooms[0]; croom->hx >= 0; croom++)
  589.         if((type == ANY_TYPE && croom->rtype != OROOM) ||
  590.            (type == ANY_SHOP && croom->rtype >= SHOPBASE) ||
  591.            croom->rtype == type)
  592.         return croom;
  593.     return (struct mkroom *) 0;
  594. }
  595.  
  596. #endif /* OVL0 */
  597. #ifdef OVLB
  598.  
  599. struct permonst *
  600. courtmon()
  601. {
  602.     int     i = rn2(60) + rn2(3*level_difficulty());
  603.     if (i > 100)        return(mkclass(S_DRAGON,0));
  604.     else if (i > 95)    return(mkclass(S_GIANT,0));
  605.     else if (i > 85)    return(mkclass(S_TROLL,0));
  606.     else if (i > 75)    return(mkclass(S_CENTAUR,0));
  607.     else if (i > 60)    return(mkclass(S_ORC,0));
  608.     else if (i > 45)    return(&mons[PM_BUGBEAR]);
  609.     else if (i > 30)    return(&mons[PM_HOBGOBLIN]);
  610.     else if (i > 15)    return(mkclass(S_GNOME,0));
  611.     else            return(mkclass(S_KOBOLD,0));
  612. }
  613.  
  614. #ifdef ARMY
  615. #define        NSTYPES    (PM_CAPTAIN-PM_SOLDIER+1)
  616.  
  617. static struct {
  618.     unsigned    pm;
  619.     unsigned    prob;
  620. } squadprob[NSTYPES] = {
  621.     {PM_SOLDIER, 80}, {PM_SERGEANT, 15}, {PM_LIEUTENANT, 4}, {PM_CAPTAIN, 1}
  622. };
  623.  
  624. static struct permonst *
  625. squadmon()        /* return soldier types. */
  626. {
  627.     register struct permonst *ptr;
  628.     register int    i, cpro, sel_prob = rnd(80+level_difficulty());
  629.  
  630.     for(cpro = i = 0; i < NSTYPES; i++)
  631.         if((cpro += squadprob[i].prob) > sel_prob) {
  632.  
  633.         ptr = &mons[squadprob[i].pm];
  634.         goto gotone;
  635.         }
  636.     ptr = &mons[squadprob[rn2(NSTYPES)].pm];
  637. gotone:
  638.     if(!(ptr->geno & (G_GENOD | G_EXTINCT)))  return(ptr);
  639.     else                return((struct permonst *) 0);
  640. }
  641. #endif /* ARMY */
  642.  
  643. /* 
  644.  * save_room : A recursive function that saves a room and its subrooms 
  645.  * (if any).
  646.  */
  647.  
  648. static void
  649. save_room(fd, r)
  650. int    fd;
  651. struct mkroom *r;
  652. {
  653.     short i;
  654.     /* 
  655.      * Well, I really should write only useful informations instead
  656.      * of writing the whole structure. That is I should not write
  657.      * the subrooms pointers, but who cares ?
  658.      */
  659.     bwrite(fd, (genericptr_t) r, sizeof(struct mkroom));
  660.     for(i=0; i<r->nsubrooms; i++)
  661.         save_room(fd, r->sbrooms[i]);
  662. }
  663.  
  664. /* 
  665.  * save_rooms : Save all the rooms on disk!
  666.  */
  667.  
  668. void
  669. save_rooms(fd)
  670. int fd;
  671. {
  672.     short i;
  673.  
  674.     /* First, write the number of rooms */
  675.     bwrite(fd, (genericptr_t) &nroom, sizeof(nroom));
  676.     for(i=0; i<nroom; i++)
  677.         save_room(fd, &rooms[i]);
  678. }
  679.  
  680. static void
  681. rest_room(fd, r)
  682. int fd;
  683. struct mkroom *r;
  684. {
  685.     short i;
  686.  
  687.     mread(fd, (genericptr_t) r, sizeof(struct mkroom));
  688.     for(i=0; i<r->nsubrooms; i++) {
  689.         r->sbrooms[i] = &subrooms[nsubroom];
  690.         rest_room(fd, &subrooms[nsubroom++]);
  691.     }
  692. }
  693.  
  694. /* 
  695.  * rest_rooms : That's for restore rooms. Read the rooms structure from
  696.  * the disk.
  697.  */
  698.  
  699. void
  700. rest_rooms(fd)
  701. int    fd;
  702. {
  703.     short i;
  704.  
  705.     mread(fd, (genericptr_t) &nroom, sizeof(nroom));
  706.     nsubroom = 0;
  707.     for(i = 0; i<nroom; i++) {
  708.         rest_room(fd, &rooms[i]);
  709.         rooms[i].resident = (struct monst *)0;
  710.     }
  711.     rooms[nroom].hx = -1;        /* restore ending flags */
  712.     subrooms[nsubroom].hx = -1;
  713. }
  714. #endif /* OVLB */
  715.  
  716. /*mkroom.c*/
  717.